package com.abluedog.mixin;


import com.abluedog.player.PlayerData;
import com.abluedog.state.BreakBlocksCountLoaderAndSaver;
import com.abluedog.util.PrizePool;
import com.abluedog.util.RandomUtil;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.particle.ParticleUtil;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.function.Supplier;

@Mixin(Block.class)
public class BlockMixin {

    @Shadow
    private static void dropStack(World world, Supplier<ItemEntity> itemEntitySupplier, ItemStack stack) {
    }

    @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;dropStacks(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/entity/BlockEntity;Lnet/minecraft/entity/Entity;Lnet/minecraft/item/ItemStack;)V"), method = "afterBreak", cancellable = true)
    private void injectAfterBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, BlockEntity blockEntity, ItemStack stack, CallbackInfo info) {
        PlayerData playDate = BreakBlocksCountLoaderAndSaver.getPlayDate(player);
        Random random = world.random;
        int i = RandomUtil.prizeDraw(playDate, random);
        if (i == 3) {
            info.cancel();
        } else if (i == 2) {
            Item stonePrize = PrizePool.getInstance().getStonePrize(random);
            this.dropStack(world, pos, stonePrize);
            info.cancel();
        } else if (i == 1) {
            Item diamondPrize = PrizePool.getInstance().getDiamondPrize(random);
            this.dropStack(world, pos, diamondPrize);
            Block block = state.getBlock();
            if (state.isIn(BlockTags.PICKAXE_MINEABLE)) {
                if (state.isIn(BlockTags.NEEDS_STONE_TOOL)) {

                }
                if (state.isIn(BlockTags.NEEDS_IRON_TOOL)) {

                }
                if (state.isIn(BlockTags.NEEDS_DIAMOND_TOOL)) {

                }
            }
            info.cancel();
        }
        world.addParticle(
                ParticleTypes.FIREWORK,
                pos.getX(),
                pos.getY(),
                pos.getZ(),
                random.nextGaussian() * 0.05,
                random.nextGaussian() * 0.5,
                random.nextGaussian() * 0.05
        );
    }

    @Unique
    public void dropStack(World world, BlockPos pos, ItemConvertible item) {
        double d = (double) EntityType.ITEM.getHeight() / 2.0;
        double e = (double) pos.getX() + 0.5 + MathHelper.nextDouble(world.random, -0.25, 0.25);
        double f = (double) pos.getY() + 0.5 + MathHelper.nextDouble(world.random, -0.25, 0.25) - d;
        double g = (double) pos.getZ() + 0.5 + MathHelper.nextDouble(world.random, -0.25, 0.25);
        ItemStack itemStack = new ItemStack(item);
        dropStack(world, () -> new ItemEntity(world, e, f, g, itemStack), itemStack);
    }

    @Inject(at = @At(value = "RETURN"), method = "shouldDropItemsOnExplosion", cancellable = true)
    public void injectShouldDropItemsOnExplosion(Explosion explosion, CallbackInfoReturnable<Boolean> cir) {
        cir.setReturnValue(false);
    }
}
